module Camera_Init(
	clk				,
	rst_n				,
	init_done		,
	camera_rst_n	,	
	camera_pwdn		,
	i2c_sclk			,
	i2c_sdat			,
	led_camera_init
);
///////配置摄像头
	input clk;
	input rst_n;
	output reg init_done;
	output camera_rst_n;
	output camera_pwdn;
	output i2c_sclk;
	inout i2c_sdat;
	output reg led_camera_init;
	
	reg wrreq;
	reg [7:0]cnt;
	reg wrreg_req;
	reg rdreg_req;
	reg [20:0] delay_cnt;
	reg [1:0]state;
	
	wire [15:0]addr;
	wire [7:0] wrdata;
	wire [7:0]lut_size;
	wire [23:0]lut;
	wire [7:0]rddata;
	wire rw_done;
	wire ack;
	wire Go;   //initial enable
	//仅在本模块使用
	localparam device_id = 8'h78;
	localparam addr_mode = 1'b1;
	localparam RGB = 0;
	localparam JPEG = 1;
	//可通过重定义和端口参数例化进行修改
	parameter IMAGE_TYPE   = RGB;
	parameter IMAGE_WIDTH  = 800;
	parameter IMAGE_HEIGHT = 480;
	parameter IMAGE_FLIP   = 0;
	parameter IMAGE_MIRROR = 0;
	assign camera_pwdn = 0;
	assign wrdata = lut[7:0];//寄存器数据
	assign addr = lut[23:8];//寄存器地址两个字节

	i2c_control	i2c_control_inst(
		.clk				(clk			),
		.rst_n			(rst_n		),
		.wrreq			(wrreg_req	),
		.rdreq			(0				),
		.addr				(addr			),
		.addr_mode		(addr_mode	),
		.wrdata			(wrdata		),
		.device_id		(device_id	),
		.rddata			(rddata		),
		.rw_done			(rw_done		),
		.ack				(ack			),
		.i2c_sclk		(i2c_sclk	),
		.i2c_sdat		(i2c_sdat	)
	);


	
	generate
	if (IMAGE_TYPE  == RGB)
		begin
			assign lut_size = 252;  //需要配置的摄像头寄存器 RGB模式无压缩
			case ({IMAGE_FLIP[0],IMAGE_MIRROR[0]})
				2'b00 :  begin
								camera_init_table_rgb camera_init_table(
									.addr(cnt),
									.clk(clk),
									.q(lut)
								);
								//对模块中的参数重定义
								defparam camera_init_table.IMAGE_WIDTH = IMAGE_WIDTH;
								defparam camera_init_table.IMAGE_HEIGHT = IMAGE_HEIGHT;
								defparam camera_init_table.IMAGE_FLIP = 8'h40;
								defparam camera_init_table.IMAGE_MIRROR = 4'h7;
							end
		
				2'b01 :  begin
								camera_init_table_rgb camera_init_table(
									.addr(cnt),
									.clk(clk),
									.q(lut)
								);
								defparam camera_init_table.IMAGE_WIDTH = IMAGE_WIDTH;
								defparam camera_init_table.IMAGE_HEIGHT = IMAGE_HEIGHT;
								defparam camera_init_table.IMAGE_FLIP = 8'h40;
								defparam camera_init_table.IMAGE_MIRROR = 4'h0;
							end
					
				2'b10 :  begin
								camera_init_table_rgb camera_init_table(
									.addr(cnt),
									.clk(clk),
									.q(lut)
								);
								defparam camera_init_table.IMAGE_WIDTH = IMAGE_WIDTH;
								defparam camera_init_table.IMAGE_HEIGHT = IMAGE_HEIGHT;
								defparam camera_init_table.IMAGE_FLIP = 8'h47;
								defparam camera_init_table.IMAGE_MIRROR = 4'h7;
							end

				2'b11 :  begin
								camera_init_table_rgb camera_init_table(
									.addr(cnt),
									.clk(clk),
									.q(lut)
								);
								defparam camera_init_table.IMAGE_WIDTH = IMAGE_WIDTH;
								defparam camera_init_table.IMAGE_HEIGHT = IMAGE_HEIGHT;
								defparam camera_init_table.IMAGE_FLIP = 8'h47;
								defparam camera_init_table.IMAGE_MIRROR = 4'h0;
							end		
			endcase 
		end
	else
		begin
			assign lut_size = 250;//jpeg模式需要配置的寄存器
			case ({IMAGE_FLIP[0],IMAGE_MIRROR[0]})
				2'b00 :  begin
								camera_init_table_jpeg camera_init_table(
									.addr(cnt),
									.clk(clk),
									.q(lut)
								);
								defparam camera_init_table.IMAGE_WIDTH = IMAGE_WIDTH;
								defparam camera_init_table.IMAGE_HEIGHT = IMAGE_HEIGHT;
								defparam camera_init_table.IMAGE_FLIP = 8'h40;
								defparam camera_init_table.IMAGE_MIRROR = 4'h7;
							end
		
				2'b01 :  begin
								camera_init_table_jpeg camera_init_table(
									.addr(cnt),
									.clk(clk),
									.q(lut)
								);
								defparam camera_init_table.IMAGE_WIDTH = IMAGE_WIDTH;
								defparam camera_init_table.IMAGE_HEIGHT = IMAGE_HEIGHT;
								defparam camera_init_table.IMAGE_FLIP = 8'h40;
								defparam camera_init_table.IMAGE_MIRROR = 4'h0;
							end
					
				2'b10 :  begin
								camera_init_table_jpeg camera_init_table(
									.addr(cnt),
									.clk(clk),
									.q(lut)
								);
								defparam camera_init_table.IMAGE_WIDTH = IMAGE_WIDTH;
								defparam camera_init_table.IMAGE_HEIGHT = IMAGE_HEIGHT;
								defparam camera_init_table.IMAGE_FLIP = 8'h47;
								defparam camera_init_table.IMAGE_MIRROR = 4'h7;
							end

				2'b11 :  begin
								camera_init_table_jpeg camera_init_table(
									.addr(cnt),
									.clk(clk),
									.q(lut)
								);
								defparam camera_init_table.IMAGE_WIDTH = IMAGE_WIDTH;
								defparam camera_init_table.IMAGE_HEIGHT = IMAGE_HEIGHT;
								defparam camera_init_table.IMAGE_FLIP = 8'h47;
								defparam camera_init_table.IMAGE_MIRROR = 4'h0;
							end		
			endcase 
		end	
	endgenerate 
	
	//上电并复位完成20ms后再配置摄像头，所以从上电到开始配置应该是1.0034 + 20 = 21.0034ms
	//这里为了优化逻辑，简化比较器逻辑，直接使延迟比较值为24'h100800，是21.0125ms
always @ (posedge clk or negedge rst_n)
	if (!rst_n)
		delay_cnt <= 21'd0;
	else if (delay_cnt == 21'h100800)
		delay_cnt <= 21'h100800;
	else
		delay_cnt <= delay_cnt + 1'b1;
		
	assign Go = (delay_cnt == 21'h1007ff)?1'b1:1'b0;//复位完成20ms后使能配置信号
	
	//5640要求上电后其复位状态需要保持1ms，所以上电后需要1ms之后再使能释放摄像头的复位信号
	//这里为了优化逻辑，简化比较器逻辑，直接使延迟比较值为24'hC400，是1.003520ms
	assign camera_rst_n = (delay_cnt >= 24'h00C400) ? 1'b1:1'b0;
//	assign camera_rst_n = 1;
	
always @ (posedge clk or negedge rst_n)
	if (!rst_n)
		cnt <= 8'd0;
	else if (Go)
		cnt <= 8'd0;
	else if (cnt < lut_size)
		begin
			if (rw_done && (!ack))
				cnt <= cnt + 1'b1;
			else
				cnt <= cnt;
		end
	else
		cnt <= 8'd0;
		
always @ (posedge clk or negedge rst_n)
	if (!rst_n)
		init_done <= 1'b0;
	else if (Go)
		init_done <= 1'b0;
	else if (cnt == lut_size)
		init_done <= 1'b1;
		
always @ (posedge clk or negedge rst_n)	
	if (!rst_n)
		led_camera_init <= 1;
	else if (init_done)
		led_camera_init <= 0;
	else
		led_camera_init <= led_camera_init;
		
always @ (posedge clk or negedge rst_n)
	if (!rst_n)
		begin
			state <= 0;
			wrreg_req <= 0;
		end
	else if (cnt < lut_size)
		begin
			case (state)
				0	:	begin
							if (Go)
								state <= 1;
							else
								state <= 0;
						end
						
				1	:	begin
							wrreg_req <= 1;
							state <= 2;
						end
						
				2	:	begin
							wrreg_req <= 0;
							if (rw_done)
								state <= 1;
							else
								state <= 2;
						end
				default : state <= 0;
			endcase
		end
	else
		state <= 0;
	

endmodule 



